博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用py 和flask 实现的服务器系统目录浏览,日志文件实时显示到网页的功能
阅读量:5330 次
发布时间:2019-06-14

本文共 8938 字,大约阅读时间需要 29 分钟。

看日志希望带有彩色,希望从浏览器上看到,不用连到机器上看。

 浏览系统的文件夹,scan + 系统文件夹的层级名字当做url路由,可以深层次看到机器上任何层级的文件夹,实现系统文件夹浏览下载。

如果是点击文件夹进入子目录。

如果是点击文件,尝试以文本格式读取文件,并以实时更新的方式显示到浏览器日志控制台并加彩。 主要是要做到不遗漏推送日志和不重复推送日志,采用的是python 操作文件的seek和tell。

 

浏览系统目录和下载文件的页面

 

 

 

 

查看实时日志更新的页面,提供了暂停功能和自动下拉功能。把日志根据级别加了彩色,更容易观察哪些是严重的,哪些是debug的。

 

 

实现代码。

# -*- coding: utf-8 -*-# @Author  : ydf# @Time    : 2019/6/14 17:33import osfrom pathlib import Pathfrom flask import Flask, send_from_directory, url_for, jsonify, request, render_template, current_app, abort, g, send_filefrom flask_httpauth import HTTPBasicAuthfrom flask_bootstrap import Bootstrapfrom app.utils_ydf import LogManager, nb_print, time_utilprint(str((Path(__file__).parent / Path('ydf_dir')).absolute()))app = Flask(__name__, template_folder=str((Path(__file__).parent / Path('ydf_dir')).absolute()))app.config['JSON_AS_ASCII'] = Falseapp.config['REFRESH_MSEC'] = 1000auth = HTTPBasicAuth()LogManager(app.logger.name).get_logger_and_add_handlers()bootstrap = Bootstrap(app)@app.route('/favicon.ico')def favicon():    print(Path(__file__).parent / Path('ydf_dir/').absolute())    return send_from_directory(str(Path(__file__).parent / Path('ydf_dir/').absolute()),                               'log_favicon.ico', mimetype='image/vnd.microsoft.icon')@app.route("/ajax0/
/")def info0(fullname): fullname = f'/{fullname}' position = int(request.args.get('position')) current_app.logger.debug(position) # if os.path.isfile(full_name): # fo = open(full_name,encoding='utf8') # content = fo.read() # return content # else : # return "There is no log file" with open(fullname, 'rb') as f: try: if position == 0: f.seek(-50000, 2) else: f.seek(position, 0) except Exception: current_app.logger.exception('读取错误') f.seek(0, 0) content_text = f.read().decode() # nb_print([content_text]) content_text = content_text.replace('\n', '
') # nb_print(content_text) position_new = f.tell() current_app.logger.debug(position_new) # nb_print(len(content_text)) return jsonify(content_text=content_text, position=position_new)@app.route("/ajax/
/")def info(fullname): fullname = f'/{fullname}' position = int(request.args.get('position')) current_app.logger.debug(position) # if os.path.isfile(full_name): # fo = open(full_name,encoding='utf8') # content = fo.read() # return content # else : # return "There is no log file" with open(fullname, 'rb') as f: try: if position == 0: f.seek(-50000, 2) else: f.seek(position, 0) except Exception: current_app.logger.exception('读取错误') f.seek(0, 0) lines = f.readlines() content_text = '' for line in lines: line = line.strip().decode() if '- DEBUG -' in line: color = '#00FF00' elif '- INFO -' in line: color = '#00FFFF' elif '- WARNING -' in line: color = 'yellow' elif '- ERROR -' in line: color = '#FF00FF' elif '- CRITICAL -' in line: color = '#FF0033' else: color = '' content_text += f'

{line}

' # content_text = f.read().decode() # # nb_print([content_text]) # content_text = content_text.replace('\n', '
') # # nb_print(content_text) position_new = f.tell() current_app.logger.debug(position_new) # nb_print(content_text) return jsonify(content_text=content_text, position=position_new)@app.route("/view/
")def view(fullname): view_html = '''
查看 %s

 
ON
''' # return view_html % (logfilename,logfilename,logfilename,logfilename,logfilename, REFRESH_MSEC, REFRESH_MSEC) return render_template('/log_view_html.html', fullname=fullname)@app.route('/download/
', )def download_file(fullname): current_app.logger.debug(fullname) return send_file(f'/{fullname}') # return send_from_directory(f'/{logs_dir}', # filename, as_attachment=True, )@app.route('/scan/', )@app.route('/scan/
', )def index(logs_dir=''): current_app.logger.debug(logs_dir) file_ele_list = list() dir_ele_list = list() for f in (Path('/') / Path(logs_dir)).iterdir(): fullname = str(f).replace('\\', '/') if f.is_file(): # current_app.logger.debug(str(f).replace('\\', '/')[1:]) # current_app.logger.debug((logs_dir, str(f).replace('\\','/')[1:])) current_app.logger.debug(str(f)) current_app.logger.debug(url_for('download_file', fullname=fullname[0:])) # current_app.logger.debug(url_for('download_file', logs_dir='', filename='windows_to_linux_syn_config.json')) file_ele_list.append({
'is_dir': 0, 'filesize': os.path.getsize(f) / 1000000, 'last_modify_time': time_util.DatetimeConverter(os.stat(str(fullname)).st_mtime).datetime_str, 'url': url_for('view', fullname=fullname[1:]), 'download_url': url_for('download_file', fullname=fullname[1:]), 'fullname': fullname}) if f.is_dir(): fullname = str(f).replace('\\', '/') dir_ele_list.append({
'is_dir': 1, 'filesize': 0, 'last_modify_time': time_util.DatetimeConverter(os.stat(str(f)).st_mtime).datetime_str, 'url': url_for('index', logs_dir=fullname[1:]), 'download_url': url_for('index', logs_dir=fullname[1:]), 'fullname': fullname}) return render_template('dir_view.html', ele_list=dir_ele_list + file_ele_list, logs_dir=logs_dir)@app.template_filter()def file_filter(filefullname, file_name_part): if file_name_part == 1: return str(Path(filefullname).parent) if file_name_part == 2: return str(Path(filefullname).name)@app.context_processordef dir_processor(): def format_logs_dir_to_multi(logs_dir): parent_dir_list = list() pa = Path(f'/{logs_dir}') while True: nb_print(pa.as_posix()) parent_dir_list.append({
'url': url_for('index', logs_dir=pa.as_posix()[1:]), 'dir_name': pa.name[:]}) pa = pa.parent if pa == Path('/'): parent_dir_list.append({
'url': url_for('index', logs_dir=''), 'dir_name': '根目录'}) break nb_print(parent_dir_list) return parent_dir_list return dict(format_logs_dir_to_multi=format_logs_dir_to_multi)@auth.verify_passworddef verify_password(username, password): if username == 'user' and password == 'mtfy123': return True return False@app.before_request@auth.login_requireddef before_request(): passif __name__ == "__main__": # main() print(app.url_map) app.run(host="0.0.0.0", port=8888, threaded=True, )

 

dir_view.html

{% extends 'bootstrap/base.html' %}​{
% block title %} {
{ logs_dir }} {% endblock %}{
% block scripts %} {
{ super() }} {
% endblock %}{
% block content %}   
常用文件夹
pythonlogs/
data/supervisorout/
{
#
#}
{
% for ele in ele_list %} {
% if ele.is_dir %}
{
% else %}
{
% endif %}
{
% endfor %}
/ {
{ logs_dir }} 的文件浏览
{% for dir_item in format_logs_dir_to_multi(logs_dir)|reverse %} /
{
{ dir_item.dir_name }}
{
% endfor %}  的文件浏览
下载文件
{ { ele.fullname | file_filter(2) }} {
{ ele.last_modify_time }}
{
{ ele.filesize }} M
下载 { { ele.fullname | file_filter(2) }}
{
% endblock %}

 

log_view.html

    
查看 {<div></div> { fullname| file_filter(2) }}

 
ON

 

转载于:https://www.cnblogs.com/ydf0509/p/11032904.html

你可能感兴趣的文章
【BZOJ 3669】 [Noi2014]魔法森林 LCT维护动态最小生成树
查看>>
[搬运] 写给 C# 开发人员的函数式编程
查看>>
vsftpd虚拟用户【公司系统部分享】
查看>>
Python之旅Day14 JQuery部分
查看>>
core--线程池
查看>>
redux-effect
查看>>
Swift和OC混编
查看>>
Android轻量级的开源缓存框架ASimpleCache
查看>>
他山之石:加载图片的一个小问题
查看>>
shell - 常识
查看>>
mssql sqlserver 使用sql脚本 清空所有数据库表数据的方法分享
查看>>
分层图最短路【bzoj2763】: [JLOI2011]飞行路线
查看>>
linux下编译复数类型引发的错误:expected unqualified-id before '(' token
查看>>
codeforces 1041A Heist
查看>>
字典常用方法
查看>>
Spring Cloud Stream消费失败后的处理策略(三):使用DLQ队列(RabbitMQ)
查看>>
python的猴子补丁monkey patch
查看>>
架构模式: API网关
查看>>
正则验证积累
查看>>
Linux学习-汇总
查看>>